#include "client-trans_file.h"

int init_train(train_t *train){
    train->type=0;
    train->length=0;
    size_t size=sizeof(train->arr);
    bzero(train->arr,size);
    return 0;
}

int init_file_msg(file_msg_t *msg){
    msg->fd=-1;
    msg->transed_byte=0;
    bzero(msg->filename,sizeof(msg->filename));
    bzero(msg->hash_file,sizeof(msg->hash_file));
    return 0;
}

int down_file(int sockfd,char *filename){
    train_t train;
    init_train(&train);
    file_msg_t file_mes;
    init_file_msg(&file_mes);
    struct stat file_stat;
    stat(filename,&file_stat);

    train.type=gets_file;
     train.length=0;
     send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);//通知服务端启动对应函数


    //传输必要的元信息
    init_train(&train);
    train.type=file_name;
    train.length=strlen(filename);
    strcpy(train.arr,filename);
    send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);//文件名发送完毕

    init_train(&train);
    train.type=cur_size;
    train.length=file_stat.st_size;
    send(sockfd,&train,sizeof(train.type)+sizeof(train.length),0);//发送当前字节数
                                                                  //
    int fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666); // 自动定位到末尾
    while(1){
        init_train(&train);
        recv_train(sockfd,&train);
        write(fd,train.arr,train.length);

        if(train.length==0){
            break;
        }

    }
    close(fd);

    return 0;
}

int recv_train(int netfd,train_t *train){
    init_train(train);
    recv(netfd,&train->type,sizeof(train->type),0);
    recv(netfd,&train->length,sizeof(train->length),0);
    recv(netfd,train->arr,train->length,0);
    return 0;
}

int caculate_hash(char *filepath,char *sha){
    EVP_MD_CTX *ctx=EVP_MD_CTX_new();
    if(!ctx) return -1;

    unsigned char temp[32]={0};
    const EVP_MD *algorithm=EVP_sha256();
    unsigned int hash_length=32;

    EVP_DigestInit_ex(ctx,algorithm,NULL);
    char buf[4096]={0};

    int fd=open(filepath,O_RDWR);
    while(1){
        bzero(buf,sizeof(buf));
        ssize_t ret=read(fd,buf,sizeof(buf));
        EVP_DigestUpdate(ctx,buf,ret);
        if(ret==0)   break;
    }

    EVP_DigestFinal_ex(ctx,temp,&hash_length);
    for (int i = 0; i < 32; i++) {
        sprintf(sha + i*2, "%02x", temp[i]);
    }

    close(fd);
    EVP_MD_CTX_free(ctx);

    return 0;
}
int up_file(int sockfd,char *filename){
    train_t train;
    init_train(&train);
    file_msg_t file_mes;
    init_file_msg(&file_mes);

    train.type=puts_file;
    train.length=0;
    send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);//通知服务端启动对应函数

    init_train(&train);
    strcpy(train.arr,filename);
    train.type=file_name;
    train.length=strlen(train.arr);
    send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);//send file name

    printf("before caculate hash\n");
    caculate_hash(filename,file_mes.hash_file);
    init_train(&train);
    train.type=file_hash;
    strcpy(train.arr,file_mes.hash_file);
    train.length=strlen(train.arr);
    send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);//send file hash

    printf("after caculate hash\n");
    recv_train(sockfd,&train);

    
    if(train.type==dont_send){//文件已经存在，不用发送了

        printf("up ok\n");
        return 0;
    }
    else{//乖乖发吧

        int fd=open(filename,O_RDWR);
        while(1){
            init_train(&train);
            train.type=file_txt;
            ssize_t rret=read(fd,train.arr,sizeof(train.arr));
            train.length=rret;

            send(sockfd,&train,sizeof(train.type)+sizeof(train.length)+train.length,0);

            if(rret==0){
                break;
            }
        }
        close(fd);
    }
    return 0;
}
